/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mahumLogs.beans;

import com.jcraft.jsch.Channel;
import com.librairies.exceptions.CommandFailException;
import com.mahumLogs.backedbeans.Configuration;
import com.mahumLogs.backedbeans.Etudiant;
import com.mahumLogs.backedbeans.Promotion;
import com.mahumLogs.utils.LogsLector;
import com.mahumLogs.utils.MyReader;
import com.mahumLogs.utils.LogsFile;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.FacesListener;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.UserTransaction;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;

/**
 *
 * @author Adrien
 */
@Named
@RequestScoped
public class FileUploadBean {

    @Resource
    private UserTransaction tx;
    @PersistenceContext
    private EntityManager em;
    private String fileName;
    private File location;
    
    @Inject
    private ConfigurationBean confBean;
    
    @Inject
    private ImportationBean importBean;
    
    private @Inject ScanLogsBean scanBean;
    
    private String promoInclu;
    private String promoExclu;

    RequestContext context = RequestContext.getCurrentInstance();
    
    public FileUploadBean() {
    }

    public void upload(FileUploadEvent event) {
        ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();
        
        location = new File(extContext.getRealPath("//resources//import_csv//"));
        fileName = event.getFile().getFileName();

        try {
            copyFile(fileName, event.getFile().getInputstream());
            importToDataBase();
        } 
        catch (IOException e) {
            e.getMessage();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Erreur", "Le fichier n'a pas été uploadé."));
            context.update("growl");
        }
    }
    
    public void uploadLogs(FileUploadEvent event) {
        ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();
        location = new File(extContext.getRealPath("//admin//files//"));
        fileName = event.getFile().getFileName();
        System.err.println("import in " + fileName + " to " + location);
        for(LogsFile f : this.scanBean.getFilesToAnalyse()){
            if(f.getFilename().equals(fileName)){
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Fichier existant", "Le fichier est déjà importé !"));
                context.update("growl");
                return;
            }
        }
        try {
            LogsFile logsFile = new LogsFile();
            logsFile.setFilename(fileName);
            logsFile.setPath(location.getAbsolutePath());
            copyFile(fileName, event.getFile().getInputstream());
            countNumberOfLine(logsFile);
            this.scanBean.addFileToAnalyse(logsFile);
            context.update("analyseFilesForm:listLogsFiles");
            context.update("analyseFilesForm:buttonAnalyse");
        } 
        catch (IOException e) {
            e.printStackTrace();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(null, "Le fichier n'a pas été uploadé."));
            context.update("growl");
        }
    }
    
    

    public void copyFile(String fileName, InputStream in) {
        try {
            try (OutputStream out = new FileOutputStream(new File(location + "//" + fileName))) {
                int read = 0;
                byte[] bytes = new byte[1024];

                while ((read = in.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }
                in.close();
                out.flush();
            }
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("OK", "Fichier sauvegardé, importation en cours ..."));
            context.update("growl");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
    
    public void countNumberOfLine(LogsFile logsFile){
        RandomAccessFile file; 
        try {
            file = new RandomAccessFile(location + "//" + fileName, "r");
            int lines = 0; 
            String line = "";
            String precLine = "";
            try {
                //On recupere la première ligne du fichier de logs afin d'obtenir la date de début des logs
                line = file.readLine();
                lines++;
                long timestampDeb = getTimestamp(line);
                logsFile.setStartTimestamp(new Date(timestampDeb));
                while ((line = file.readLine()) != null) { 
                    lines++;
                    precLine = line;
                }
                //On recupere la dernière ligne du fichier de logs afin d'obtenir la date de fin des logs
                long timestampEnd = getTimestamp(precLine);
                System.out.println(timestampEnd);
                logsFile.setEndTimestamp(new Date(timestampEnd));
                logsFile.setNbLignes(lines);
            } catch (IOException ex) {
                Logger.getLogger(FileUploadBean.class.getName()).log(Level.SEVERE, null, ex);
            }
            System.out.println("Number " + lines);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(FileUploadBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public long getTimestamp(String line){
        try {
            return Long.valueOf(line.replace("\\s+", " ").split(" ")[0]);
        } catch (Exception ex) {
        }
        
        return -1;
    }

    public void importToDataBase() throws FileNotFoundException, IOException {
        BufferedReader file = null;
        try {
            file = new BufferedReader(new FileReader(location + "//" + fileName));
            String strContent;
            Etudiant etudiant = null;
            Query query = null;
            List<Promotion> lesPromotions = new ArrayList();
            List<Etudiant> lesEtudiantsExistants = new ArrayList();
            
            int i = 1;
            Query query2 = em.createQuery("SELECT p FROM Promotion p");
            Query query3 = em.createQuery("SELECT e FROM Etudiant e");
            lesPromotions = query2.getResultList();
            lesEtudiantsExistants = query3.getResultList();
            importBean.getImported().clear();
            try {
                while ((strContent = file.readLine()) != null) {
                    String[] tabStr = strContent.split(";");
                    for (int j = 0; j < lesPromotions.size(); j++) {
                        if ((tabStr[4].equals(lesPromotions.get(j).getLibelle()))) {
                            etudiant = new Etudiant();
                            
                            //On encrypte le mot de passe en MD5
                            try {
                                MessageDigest m;
                                try {
                                    m = MessageDigest.getInstance("MD5");
                                    m.update(tabStr[1].getBytes("UTF8"));
                                    byte s[] = m.digest();
                                    String result = "";

                                    for (int u = 0; u < s.length; u++) {
                                      result += Integer.toHexString((0x000000ff & s[u]) | 0xffffff00).substring(6);
                                    }
                                    System.out.println(result);
                                    etudiant.setPassword(result);
                                    etudiant.setLogin(tabStr[0]);
                                    etudiant.setNom(tabStr[2]);
                                    etudiant.setPrenom(tabStr[3]);
                                    etudiant.setPromotion(lesPromotions.get(j));
                                    // On verifie si l'etudiant n'existe pas deja
                                    if(!etudiantExist(lesEtudiantsExistants, etudiant)){
                                        // On verifie que l'IP est correct et on envoie à la base de données
                                        if (verificationIpEtudiant(etudiant)) {
                                            tx.begin();
                                            em.merge(etudiant);
                                            tx.commit();
                                            importBean.addImportedEtudiant(etudiant);
                                        }
                                    }
                                    
                                } catch (NoSuchAlgorithmException ex) {
                                    Logger.getLogger(LoginBean.class.getName()).log(Level.SEVERE, null, ex);
                                }
                            } catch (Exception ex) {
                                ex.printStackTrace();
                            }
                        } else {
                        }
                    }
                    i++;
                }
                file.close();
            } catch (IOException ex) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(null, "Problème d'importation.7"));
                context.update("growl");
                ex.printStackTrace();
            } finally {
                file.close();
            }
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }
    }
    
    private boolean etudiantExist(List<Etudiant> etudiants, Etudiant etudiant){
        for(Etudiant e : etudiants){
            if(e.getLogin().equals(etudiant.getLogin())){
                return true;
            }
        }
        return false;
    }

    public boolean verificationIpEtudiant(Etudiant etudiant) {
        Configuration dhcpDebutPlage = confBean.findByKey("DHCP_DEBUT_PLAGE");
        Configuration dhcpFinPlage = confBean.findByKey("DHCP_FIN_PLAGE");
        String maskEtudiant;
        boolean maxAdresses;
        //extract en int de l'octet à incrémenter   
        //debut plage
        int position = dhcpDebutPlage.getValeur().lastIndexOf(".");
        String stringDebutOctet = dhcpDebutPlage.getValeur().substring(position + 1);
        int intDebutOctet = Integer.parseInt(stringDebutOctet);
        //fin plage
        String stringfinOctet = dhcpFinPlage.getValeur().substring(position + 1);
        int intFinOctet = Integer.parseInt(stringfinOctet);
        //reste des octets
        String premierOctet = dhcpDebutPlage.getValeur().substring(0, position);
        //Nombre de masques possibles
        int plageEtudiant = (intFinOctet - intDebutOctet) + 1;
        //test si adresse ip présente dans base
        Query query = em.createQuery("SELECT e FROM Etudiant e");

        List<Etudiant> etudiants = query.getResultList();
        boolean trouvePosition = false;
        System.out.println(intFinOctet);
        if (intFinOctet < 256) {
            if (etudiants.size() < plageEtudiant) {
                etudiant.setIpMask(dhcpDebutPlage.getValeur());
                for (int i = intDebutOctet; i < (intFinOctet + 1) && !trouvePosition; i++) {
                    maskEtudiant = premierOctet + "." + i;
                    for (Etudiant e : etudiants) {
                        if (e.getIpMask().equals(maskEtudiant)) {
                            trouvePosition = false;
                            break;
                        } else {
                            trouvePosition = true;
                        }
                    }

                    if (trouvePosition) {
                        System.out.println("Attribution de la valeur " + maskEtudiant);
                        etudiant.setIpMask(maskEtudiant);
                    }
                }
                maxAdresses = true;
                return maxAdresses;
            } else {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur d'ajout de "
                        + etudiant.getPrenom() + etudiant.getNom(),
                        "Trop d'étudiants pour la plage DHCP"));
                maxAdresses = false;
                return maxAdresses;
            }
        } else {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur d'ajout",
                    "Plage DHCP supèrieure à 255"));
            maxAdresses = false;
            return maxAdresses;
        }
    }

    public UserTransaction getTx() {
        return tx;
    }

    public void setTx(UserTransaction tx) {
        this.tx = tx;
    }

    public EntityManager getEm() {
        return em;
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public File getLocation() {
        return location;
    }

    public void setLocation(File location) {
        this.location = location;
    }

    public String getPromoInclu() {
        return promoInclu;
    }

    public void setPromoInclu(String promoInclu) {
        this.promoInclu = promoInclu;
    }

    public String getPromoExclu() {
        return promoExclu;
    }

    public void setPromoExclu(String promoExclu) {
        this.promoExclu = promoExclu;
    }
}
